"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.BaseForm = BaseForm;

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _objectSpread4 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

var _regeneratorRuntime2 = _interopRequireDefault(require("@babel/runtime/helpers/regeneratorRuntime"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _jsxRuntime = require("react/jsx-runtime");

var _proProvider = require("@ant-design/pro-provider");

var _proUtils = require("@ant-design/pro-utils");

var _useParams = require("@umijs/use-params");

var _antdV = require("antd-v4");

var _get = _interopRequireDefault(require("rc-util/lib/utils/get"));

var _set = _interopRequireDefault(require("rc-util/lib/utils/set"));

var _warning = require("rc-util/lib/warning");

var _react = _interopRequireWildcard(require("react"));

var _components = require("../components");

var _FieldContext = _interopRequireDefault(require("../FieldContext"));

var _helpers = require("../helpers");

var _excluded = ["children", "contentRender", "submitter", "fieldProps", "formItemProps", "groupProps", "dateFormatter", "formRef", "onInit", "form", "formComponentType", "extraUrlParams", "syncToUrl", "syncToUrlAsImportant", "syncToInitialValues", "onReset", "omitNil", "isKeyPressSubmit", "autoFocusFirstInput", "grid", "rowProps", "colProps"],
    _excluded2 = ["request", "params", "initialValues", "formKey"];

var genParams = function genParams(syncUrl, params, type) {
  if (syncUrl === true) {
    return params;
  }

  return (0, _proUtils.runFunction)(syncUrl, params, type);
};
/**
 * It takes a name path and converts it to an array.
 * @param {NamePath} name - The name of the form.
 * @returns string[]
 *
 * a-> [a]
 * [a] -> [a]
 */


var covertFormName = function covertFormName(name) {
  if (!name) return name;
  if (Array.isArray(name)) return name;
  return [name];
};

function BaseFormComponents(props) {
  var children = props.children,
      contentRender = props.contentRender,
      submitter = props.submitter,
      fieldProps = props.fieldProps,
      formItemProps = props.formItemProps,
      groupProps = props.groupProps,
      _props$dateFormatter = props.dateFormatter,
      dateFormatter = _props$dateFormatter === void 0 ? 'string' : _props$dateFormatter,
      propsFormRef = props.formRef,
      onInit = props.onInit,
      form = props.form,
      formComponentType = props.formComponentType,
      _props$extraUrlParams = props.extraUrlParams,
      extraUrlParams = _props$extraUrlParams === void 0 ? {} : _props$extraUrlParams,
      syncToUrl = props.syncToUrl,
      _props$syncToUrlAsImp = props.syncToUrlAsImportant,
      syncToUrlAsImportant = _props$syncToUrlAsImp === void 0 ? false : _props$syncToUrlAsImp,
      _props$syncToInitialV = props.syncToInitialValues,
      syncToInitialValues = _props$syncToInitialV === void 0 ? true : _props$syncToInitialV,
      _onReset = props.onReset,
      _props$omitNil = props.omitNil,
      omitNil = _props$omitNil === void 0 ? true : _props$omitNil,
      isKeyPressSubmit = props.isKeyPressSubmit,
      _props$autoFocusFirst = props.autoFocusFirstInput,
      autoFocusFirstInput = _props$autoFocusFirst === void 0 ? true : _props$autoFocusFirst,
      grid = props.grid,
      rowProps = props.rowProps,
      colProps = props.colProps,
      rest = (0, _objectWithoutProperties2.default)(props, _excluded);
  var sizeContextValue = (0, _react.useContext)(_antdV.ConfigProvider.SizeContext);

  var _Form$useForm = _antdV.Form.useForm(form),
      _Form$useForm2 = (0, _slicedToArray2.default)(_Form$useForm, 1),
      inlineForm = _Form$useForm2[0];
  /** 同步 url 上的参数 */


  var _useUrlSearchParams = (0, _useParams.useUrlSearchParams)({}, {
    disabled: !syncToUrl
  }),
      _useUrlSearchParams2 = (0, _slicedToArray2.default)(_useUrlSearchParams, 2),
      urlSearch = _useUrlSearchParams2[0],
      setUrlSearch = _useUrlSearchParams2[1];

  var formRef = (0, _react.useRef)(inlineForm || {});

  var _useGridHelpers = (0, _helpers.useGridHelpers)({
    grid: grid,
    rowProps: rowProps
  }),
      RowWrapper = _useGridHelpers.RowWrapper;

  var fieldsValueType = (0, _react.useRef)({});
  /** 保存 transformKeyRef，用于对表单key transform */

  var transformKeyRef = (0, _react.useRef)({});
  /** 使用 callback 的类型 */

  var transformKey = (0, _react.useCallback)(function (values, omit, parentKey) {
    return (0, _proUtils.transformKeySubmitValue)((0, _proUtils.conversionMomentValue)(values, dateFormatter, fieldsValueType.current, omit, parentKey), transformKeyRef.current, omit);
  }, [dateFormatter]);
  var formatValues = (0, _react.useMemo)(function () {
    return {
      /**
       * 获取被 ProForm 格式化后的所有数据
       * @param allData boolean
       * @returns T
       *
       * @example  getFieldsFormatValue(true) ->返回所有数据，即使没有被 form 托管的
       */
      getFieldsFormatValue: function getFieldsFormatValue(allData) {
        var _formRef$current;

        return transformKey((_formRef$current = formRef.current) === null || _formRef$current === void 0 ? void 0 : _formRef$current.getFieldsValue(allData), omitNil);
      },

      /**
       * 获取被 ProForm 格式化后的单个数据
       * @param nameList (string|number)[]
       * @returns T
       *
       * @example {a:{b:value}} -> getFieldFormatValue(['a', 'b']) -> value
       */

      /** 获取格式化之后的单个数据 */
      getFieldFormatValue: function getFieldFormatValue() {
        var _formRef$current2;

        var paramsNameList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
        var nameList = covertFormName(paramsNameList);
        if (!nameList) throw new Error('nameList is require');
        var value = (_formRef$current2 = formRef.current) === null || _formRef$current2 === void 0 ? void 0 : _formRef$current2.getFieldValue(nameList);
        var obj = nameList ? (0, _set.default)({}, nameList, value) : value;
        return (0, _get.default)(transformKey(obj, omitNil, nameList), nameList);
      },

      /**
       * 获取被 ProForm 格式化后的单个数据, 包含他的 name
       * @param nameList (string|number)[]
       * @returns T
       *
       * @example  {a:{b:value}} -> getFieldFormatValueObject(['a', 'b']) -> {a:{b:value}}
       */

      /** 获取格式化之后的单个数据 */
      getFieldFormatValueObject: function getFieldFormatValueObject(paramsNameList) {
        var _formRef$current3;

        var nameList = covertFormName(paramsNameList);
        var value = (_formRef$current3 = formRef.current) === null || _formRef$current3 === void 0 ? void 0 : _formRef$current3.getFieldValue(nameList);
        var obj = nameList ? (0, _set.default)({}, nameList, value) : value;
        return transformKey(obj, omitNil, nameList);
      },

      /**
      /**
       *验字段后返回格式化之后的所有数据
       * @param nameList (string|number)[]
       * @returns T
       *
       * @example validateFieldsReturnFormatValue -> {a:{b:value}}
       */
      validateFieldsReturnFormatValue: function () {
        var _validateFieldsReturnFormatValue = (0, _asyncToGenerator2.default)( /*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee(nameList) {
          var _formRef$current4;

          var values, transformedKey;
          return (0, _regeneratorRuntime2.default)().wrap(function _callee$(_context) {
            while (1) {
              switch (_context.prev = _context.next) {
                case 0:
                  if (!(!Array.isArray(nameList) && nameList)) {
                    _context.next = 2;
                    break;
                  }

                  throw new Error('nameList must be array');

                case 2:
                  _context.next = 4;
                  return (_formRef$current4 = formRef.current) === null || _formRef$current4 === void 0 ? void 0 : _formRef$current4.validateFields(nameList);

                case 4:
                  values = _context.sent;
                  transformedKey = transformKey(values, omitNil);
                  return _context.abrupt("return", transformedKey ? transformedKey : {});

                case 7:
                case "end":
                  return _context.stop();
              }
            }
          }, _callee);
        }));

        function validateFieldsReturnFormatValue(_x) {
          return _validateFieldsReturnFormatValue.apply(this, arguments);
        }

        return validateFieldsReturnFormatValue;
      }(),
      formRef: formRef
    };
  }, [omitNil, transformKey]);
  /** 利用反射把值传的到处都是，并且总是新的 */

  var responseForm = (0, _react.useMemo)(function () {
    var response = (0, _objectSpread4.default)({}, formRef.current);
    Object.keys(formRef.current || {}).forEach(function (key) {
      Object.defineProperty(response, key, {
        get: function get() {
          return formRef.current[key];
        }
      });
    });
    Object.keys(formatValues).forEach(function (key) {
      Object.defineProperty(response, key, {
        get: function get() {
          return formatValues[key];
        }
      });
    });
    return response; // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  var _useMountMergeState = (0, _proUtils.useMountMergeState)(false),
      _useMountMergeState2 = (0, _slicedToArray2.default)(_useMountMergeState, 2),
      loading = _useMountMergeState2[0],
      setLoading = _useMountMergeState2[1];

  var items = (0, _react.useMemo)(function () {
    return _react.default.Children.toArray(children).map(function (item, index) {
      if (index === 0 && /*#__PURE__*/_react.default.isValidElement(item) && autoFocusFirstInput) {
        return /*#__PURE__*/_react.default.cloneElement(item, (0, _objectSpread4.default)((0, _objectSpread4.default)({}, item.props), {}, {
          autoFocus: autoFocusFirstInput
        }));
      }

      return item;
    });
  }, [autoFocusFirstInput, children]);
  /** 计算 props 的对象 */

  var submitterProps = (0, _react.useMemo)(function () {
    return typeof submitter === 'boolean' || !submitter ? {} : submitter;
  }, [submitter]); // 初始化给一个默认的 form

  (0, _react.useImperativeHandle)(propsFormRef, function () {
    return responseForm;
  });
  /** 渲染提交按钮与重置按钮 */

  var submitterNode = (0, _react.useMemo)(function () {
    if (submitter === false) return undefined;
    return (0, _jsxRuntime.jsx)(_components.Submitter, (0, _objectSpread4.default)((0, _objectSpread4.default)({}, submitterProps), {}, {
      onReset: function onReset() {
        var _formRef$current5, _submitterProps$onRes;

        var finalValues = transformKey((_formRef$current5 = formRef.current) === null || _formRef$current5 === void 0 ? void 0 : _formRef$current5.getFieldsValue(), omitNil);
        submitterProps === null || submitterProps === void 0 ? void 0 : (_submitterProps$onRes = submitterProps.onReset) === null || _submitterProps$onRes === void 0 ? void 0 : _submitterProps$onRes.call(submitterProps, finalValues);
        _onReset === null || _onReset === void 0 ? void 0 : _onReset(finalValues); // 如果 syncToUrl，清空一下数据

        if (syncToUrl) {
          var _formRef$current6;

          // 把没有的值设置为未定义可以删掉 url 的参数
          var params = Object.keys(transformKey((_formRef$current6 = formRef.current) === null || _formRef$current6 === void 0 ? void 0 : _formRef$current6.getFieldsValue(), false)).reduce(function (pre, next) {
            return (0, _objectSpread4.default)((0, _objectSpread4.default)({}, pre), {}, (0, _defineProperty2.default)({}, next, finalValues[next] || undefined));
          }, extraUrlParams);
          /** 在同步到 url 上时对参数进行转化 */

          setUrlSearch(genParams(syncToUrl, params, 'set'));
        }
      },
      form: responseForm,
      submitButtonProps: (0, _objectSpread4.default)({
        loading: loading
      }, submitterProps.submitButtonProps)
    }), "submitter");
  }, [submitter, submitterProps, responseForm, loading, transformKey, omitNil, _onReset, syncToUrl, extraUrlParams, setUrlSearch]);
  var content = (0, _react.useMemo)(function () {
    var wrapItems = grid ? (0, _jsxRuntime.jsx)(RowWrapper, {
      children: items
    }) : items;

    if (contentRender) {
      return contentRender(wrapItems, submitterNode, formRef.current);
    }

    return wrapItems;
  }, [grid, RowWrapper, items, contentRender, submitterNode]);
  var getPopupContainer = (0, _react.useMemo)(function () {
    if (typeof window === 'undefined') return undefined; // 如果在 drawerForm 和  modalForm 里就渲染dom到父节点里
    // modalForm 可能高度太小不适合

    if (formComponentType && ['DrawerForm'].includes(formComponentType)) {
      return function (e) {
        return e.parentNode || document.body;
      };
    }

    return undefined;
  }, [formComponentType]);
  (0, _react.useEffect)(function () {
    var _formRef$current7;

    var finalValues = transformKey((_formRef$current7 = formRef.current) === null || _formRef$current7 === void 0 ? void 0 : _formRef$current7.getFieldsValue(true), omitNil);
    onInit === null || onInit === void 0 ? void 0 : onInit(finalValues, responseForm); // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []); // 如果为 false，不需要触发设置进去

  var _useState = (0, _react.useState)(function () {
    if (!syncToUrl) {
      return {};
    }

    return genParams(syncToUrl, urlSearch, 'get');
  }),
      _useState2 = (0, _slicedToArray2.default)(_useState, 2),
      urlParamsMergeInitialValues = _useState2[0],
      setUrlParamsMergeInitialValues = _useState2[1];

  (0, _react.useEffect)(function () {
    if (syncToInitialValues) return;
    setUrlParamsMergeInitialValues({});
  }, [syncToInitialValues]);
  var preInitialValues = (0, _proUtils.usePrevious)(props.initialValues); // 提示一个 initialValues ，问的人实在是太多了

  (0, _react.useEffect)(function () {
    if (syncToUrl || !props.initialValues || !preInitialValues || rest.request) return;
    var isEqual = (0, _proUtils.isDeepEqualReact)(props.initialValues, preInitialValues);
    (0, _warning.noteOnce)(isEqual, "initialValues \u53EA\u5728 form \u521D\u59CB\u5316\u65F6\u751F\u6548\uFF0C\u5982\u679C\u4F60\u9700\u8981\u5F02\u6B65\u52A0\u8F7D\u63A8\u8350\u4F7F\u7528 request\uFF0C\u6216\u8005 initialValues ? <Form/> : null ");
    (0, _warning.noteOnce)(isEqual, "The initialValues only take effect when the form is initialized, if you need to load asynchronously recommended request, or the initialValues ? <Form/> : null "); // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [props.initialValues]);
  (0, _react.useEffect)(function () {
    if (!syncToUrl) return;
    setUrlSearch((0, _objectSpread4.default)((0, _objectSpread4.default)({}, urlSearch), extraUrlParams)); // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [extraUrlParams, syncToUrl]);
  return (// 增加国际化的能力，与 table 组件可以统一
    (0, _jsxRuntime.jsx)(_FieldContext.default.Provider, {
      value: {
        formRef: formRef,
        fieldProps: fieldProps,
        formItemProps: formItemProps,
        groupProps: groupProps,
        formComponentType: formComponentType,
        getPopupContainer: getPopupContainer,
        setFieldValueType: function setFieldValueType(name, _ref) {
          var _ref$valueType = _ref.valueType,
              valueType = _ref$valueType === void 0 ? 'text' : _ref$valueType,
              dateFormat = _ref.dateFormat,
              transform = _ref.transform;
          if (!Array.isArray(name)) return;
          transformKeyRef.current = (0, _set.default)(transformKeyRef.current, name, transform);
          fieldsValueType.current = (0, _set.default)(fieldsValueType.current, name, {
            valueType: valueType,
            dateFormat: dateFormat
          });
        }
      },
      children: (0, _jsxRuntime.jsx)(_proUtils.ProFormContext.Provider, {
        value: formatValues,
        children: (0, _jsxRuntime.jsx)(_antdV.ConfigProvider.SizeContext.Provider, {
          value: rest.size || sizeContextValue,
          children: (0, _jsxRuntime.jsx)(_helpers.GridContext.Provider, {
            value: {
              grid: grid,
              colProps: colProps
            },
            children: (0, _jsxRuntime.jsxs)(_antdV.Form, (0, _objectSpread4.default)((0, _objectSpread4.default)({
              onKeyPress: function onKeyPress(event) {
                if (!isKeyPressSubmit) return;

                if (event.key === 'Enter') {
                  var _formRef$current8;

                  (_formRef$current8 = formRef.current) === null || _formRef$current8 === void 0 ? void 0 : _formRef$current8.submit();
                }
              },
              form: inlineForm
            }, rest), {}, {
              // 组合 urlSearch 和 initialValues
              initialValues: syncToUrlAsImportant ? (0, _objectSpread4.default)((0, _objectSpread4.default)({}, rest.initialValues), urlParamsMergeInitialValues) : (0, _objectSpread4.default)((0, _objectSpread4.default)({}, urlParamsMergeInitialValues), rest.initialValues),
              onValuesChange: function onValuesChange(changedValues, values) {
                var _rest$onValuesChange;

                rest === null || rest === void 0 ? void 0 : (_rest$onValuesChange = rest.onValuesChange) === null || _rest$onValuesChange === void 0 ? void 0 : _rest$onValuesChange.call(rest, transformKey(changedValues, omitNil), transformKey(values, omitNil));
              },
              onFinish: function () {
                var _onFinish = (0, _asyncToGenerator2.default)( /*#__PURE__*/(0, _regeneratorRuntime2.default)().mark(function _callee2() {
                  var _formRef$current9, finalValues, _formRef$current10, params;

                  return (0, _regeneratorRuntime2.default)().wrap(function _callee2$(_context2) {
                    while (1) {
                      switch (_context2.prev = _context2.next) {
                        case 0:
                          if (rest.onFinish) {
                            _context2.next = 2;
                            break;
                          }

                          return _context2.abrupt("return");

                        case 2:
                          if (!loading) {
                            _context2.next = 4;
                            break;
                          }

                          return _context2.abrupt("return");

                        case 4:
                          setLoading(true);
                          _context2.prev = 5;
                          finalValues = transformKey((_formRef$current9 = formRef.current) === null || _formRef$current9 === void 0 ? void 0 : _formRef$current9.getFieldsValue(), omitNil);
                          _context2.next = 9;
                          return rest.onFinish(finalValues);

                        case 9:
                          if (syncToUrl) {
                            // 把没有的值设置为未定义可以删掉 url 的参数
                            params = Object.keys(transformKey((_formRef$current10 = formRef.current) === null || _formRef$current10 === void 0 ? void 0 : _formRef$current10.getFieldsValue(), false)).reduce(function (pre, next) {
                              var _finalValues$next;

                              return (0, _objectSpread4.default)((0, _objectSpread4.default)({}, pre), {}, (0, _defineProperty2.default)({}, next, (_finalValues$next = finalValues[next]) !== null && _finalValues$next !== void 0 ? _finalValues$next : undefined));
                            }, extraUrlParams); // fix #3547: 当原先在url中存在的字段被删除时，应该将 params 中的该字段设置为 undefined,以便触发url同步删除

                            Object.keys(urlSearch).forEach(function (key) {
                              if (params[key] !== false && params[key] !== 0 && !params[key]) {
                                params[key] = undefined;
                              }
                            });
                            /** 在同步到 url 上时对参数进行转化 */

                            setUrlSearch(genParams(syncToUrl, params, 'set'));
                          }

                          setLoading(false);
                          _context2.next = 16;
                          break;

                        case 13:
                          _context2.prev = 13;
                          _context2.t0 = _context2["catch"](5);
                          // console.log(error);
                          setLoading(false);

                        case 16:
                        case "end":
                          return _context2.stop();
                      }
                    }
                  }, _callee2, null, [[5, 13]]);
                }));

                function onFinish() {
                  return _onFinish.apply(this, arguments);
                }

                return onFinish;
              }(),
              children: [rest.component !== false && (0, _jsxRuntime.jsx)("input", {
                type: "text",
                style: {
                  display: 'none'
                }
              }), (0, _jsxRuntime.jsx)(_antdV.Form.Item, {
                noStyle: true,
                shouldUpdate: true,
                children: function children(formInstance) {
                  if (propsFormRef) propsFormRef.current = (0, _objectSpread4.default)((0, _objectSpread4.default)({}, formInstance), formatValues);
                  formRef.current = formInstance;
                  return null;
                }
              }), content]
            }))
          })
        })
      })
    })
  );
}
/** 自动的formKey 防止重复 */


var requestFormCacheId = 0;

function BaseForm(props) {
  var request = props.request,
      params = props.params,
      initialValues = props.initialValues,
      _props$formKey = props.formKey,
      formKey = _props$formKey === void 0 ? requestFormCacheId : _props$formKey,
      rest = (0, _objectWithoutProperties2.default)(props, _excluded2);
  (0, _react.useEffect)(function () {
    requestFormCacheId += 0;
  }, []);

  var _useFetchData = (0, _proUtils.useFetchData)({
    request: request,
    params: params,
    proFieldKey: formKey
  }),
      _useFetchData2 = (0, _slicedToArray2.default)(_useFetchData, 1),
      initialData = _useFetchData2[0];

  if (!initialData && props.request) {
    return (0, _jsxRuntime.jsx)("div", {
      style: {
        paddingTop: 50,
        paddingBottom: 50,
        textAlign: 'center'
      },
      children: (0, _jsxRuntime.jsx)(_antdV.Spin, {})
    });
  }

  return (0, _jsxRuntime.jsx)(_proProvider.ConfigProviderWrap, {
    children: (0, _jsxRuntime.jsx)(BaseFormComponents, (0, _objectSpread4.default)((0, _objectSpread4.default)({
      autoComplete: "off"
    }, rest), {}, {
      initialValues: (0, _objectSpread4.default)((0, _objectSpread4.default)({}, initialValues), initialData)
    }))
  });
}